/*************************************************************************
	> File Name: uart.c
	> Author: yuarmy
	> Mail: yuarmy@126.com 
	> Created Time: Sun 03 Aug 2014 05:26:51 AM PDT
 ************************************************************************/

#include<stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <errno.h>
#include <inttypes.h>

#define UARTNAME "/dev/ttyS2"
typedef struct tagSHDevManage {
  int32_t server_sockfd;
  int32_t client_sockfd;
  int32_t test_sockfd;
  int32_t uart_fd;
  fd_set readfds;
  fd_set writefds;
  struct termios orig_term;
  struct termios uart_term;
  int32_t client_state;
  int32_t uart_state;
}SHDEVMANAGE_T;

SHDEVMANAGE_T shdev_;
int32_t GetBaud(int32_t baud) {
  return B9600;
}

int8_t GetDataBit(int8_t config) {
  return CS8;
}
int32_t GetStopbit(config) {
  return 1;
}
int8_t GetParity(config) {
  return 'N';
}
#define  SERIAL_8N1 1
int32_t InitUartTerm(SHDEVMANAGE_T *shdev) {
  int32_t ret;
  int32_t baud, rate;
  int8_t config = SERIAL_8N1;
  int8_t buff[80] = "Hello";

  ret = open(UARTNAME, O_RDWR);
  if (ret < 0) {
	fprintf(stderr, "%s %d it is error: %d to fail to open uart.\n",
		__FILE__, __LINE__, errno);
	goto fail;
  }

  shdev->uart_fd = ret;
  tcgetattr(shdev->uart_fd, &shdev->orig_term);
  shdev->uart_term = shdev->orig_term;
  tcflush(shdev->uart_fd, TCIOFLUSH);
#if 1
  baud = 9600;
  rate = GetBaud(baud);
  if (rate > 0) {
	cfsetispeed(&shdev->uart_term, rate);
	cfsetospeed(&shdev->uart_term, rate);
  } else {
	goto fail;
  }
  shdev->uart_term.c_cflag &= ~CSIZE;
  shdev->uart_term.c_cflag &= GetDataBit(config);
  switch (GetParity(config))
  {   
	case 'N':
	default:
	  shdev->uart_term.c_cflag &= ~PARENB;
	  shdev->uart_term.c_iflag &= ~INPCK;
	  break;
	case 'O':
	  shdev->uart_term.c_cflag |= (PARODD | PARENB);
	  shdev->uart_term.c_iflag |= INPCK;
	  break;  
	case 'E':
	  shdev->uart_term.c_cflag |= PARENB;
	  shdev->uart_term.c_cflag &= ~PARODD;
	  shdev->uart_term.c_iflag |= INPCK;
	  break;
  }  

  switch (GetStopbit(config))
  {   
	case 1:
	default:
	  shdev->uart_term.c_cflag &= ~CSTOPB;  
	  break;  
	case 2:
	  shdev->uart_term.c_cflag |= CSTOPB;  
	  break;
  }

  shdev->uart_term.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
#endif
  ret = tcsetattr(shdev->uart_fd, TCSANOW, &shdev->uart_term);
  if (ret) {
	fprintf(stderr, "%s %d it is error: %d to set attr.\n",
		__FILE__, __LINE__, errno);
	goto fail;
  }
  tcflush(shdev->uart_fd, TCIOFLUSH);
  shdev->uart_state = 1;
  read(shdev->uart_fd, buff, 80);
  printf("receive data %c\n", buff[0]);

  FD_SET(shdev->uart_fd, &shdev->readfds);
  return ret;
fail:
  if (shdev->uart_fd) {
	close(shdev->uart_fd);
  }
  return ret;
}
int32_t ReadFromUart(SHDEVMANAGE_T *shdev, uint8_t* buff, int32_t size) {
  int32_t ret;

  ret = read(shdev->uart_fd, buff, size);
  return ret;
}
int32_t WriteToUart(SHDEVMANAGE_T *shdev, uint8_t* buff, int32_t size) {
  int32_t ret;

  ret = write(shdev->uart_fd, buff, size);
  return ret;
}
int32_t DeinitUartTerm(SHDEVMANAGE_T *shdev) {
  if (shdev->uart_state && shdev->uart_fd) {
	FD_CLR(shdev->uart_fd, &shdev->readfds);
	tcsetattr(shdev->uart_fd, TCSANOW, &shdev->orig_term);
	close(shdev->uart_fd);
  }
}
int main()
{
  int32_t ret;

  InitUartTerm(&shdev_);

  DeinitUartTerm(&shdev_);
fail:
  return ret;
}
